home *** CD-ROM | disk | FTP | other *** search
- // ┌────────────────────────────────────────┐
- // │ Gouraud Vectors │
- // │ coded by Tumblin / Bodies In Motion │
- // │ (Terry Sznober) │
- // │ Copyright (c) 1995 by Bodies In Motion │
- // └────────────────────────────────────────┘
- //────────────────────────────────────────────────────────────────────────
-
- // Last modified May 28, 1995
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <conio.h>
- #include <dos.h>
- #include <process.h>
- #include <xlib_all.h>
-
- #include "gvectors.h"
-
- //──────────────────────── fixed point math code ─────────────────────────
-
- typedef long Fixedpoint;
-
- #define Int2Fixed(a) (Fixedpoint)((Fixedpoint)(a) << 16)
- #define Fixed2Int(a) (int)((a) >> 16)
- #define Float2Fixed(a) ((Fixedpoint)((a) * 65536.0))
- #define Fixed2Float(a) ((a) / 65536.0)
-
- extern "C" {
- Fixedpoint FixedMul(Fixedpoint,Fixedpoint);
- Fixedpoint FixedDiv(Fixedpoint,Fixedpoint);
- };
-
-
- //--------------------------------------------------------------------------
-
- // maximum # of degrees for sin and cos tables
- #define MAXDEGREES 720
-
- // distance from users eye to screen surface in pixels
- #define EYE_DISTANCE Int2Fixed(256)
-
- //──────────────────────────── data structures ───────────────────────────
-
- char filename[80]; // filename of object to load/save
-
- Fixedpoint cosine[MAXDEGREES]; // cosine lookup table
- Fixedpoint sine[MAXDEGREES]; // sine lookup table
-
- // these are for the gouraud shading routines
- int edge_l[240];
- int edge_r[240];
- char color_l[240];
- char color_r[240];
-
- #define MAXVERTICES 300
- #define MAXPOLYGONS 300
- #define MAXPOLYVERT 20
-
- // structure of one vertex
- typedef struct
- {
- Fixedpoint Vox,Voy,Voz; // vertex original coordinates
- Fixedpoint Vwx,Vwy,Vwz; // vertex working coordinates
- int Vsx,Vsy,Vsz; // vertex screen coordinates
- Fixedpoint Nox,Noy,Noz; // normal's original coordinates
- Fixedpoint Nwx,Nwy,Nwz; // normal's working coordinates
- int shadedcolor; // color of vertex used for gouraud shading
- } VertexTYPE;
-
- // structure of one polygon
- typedef struct
- {
- int NumOfVertices; // number of vertices that make up the polygon
- int Vertex[MAXPOLYVERT]; // vertex indices in counter clockwise order
- int zcenter; // center z coordinate (used for polygon sorting)
- int color; // color group of polygon (before shading)
- int shadedcolor; // actual color value of polygon after shading
- } PolygonTYPE;
-
- // object structure
- typedef struct
- {
- Fixedpoint Ox,Oy,Oz; // coordinates of object's origin
- int Ax,Ay,Az; // object's rotation angles
- int NumOfVertices; // number of vertices in object
- VertexTYPE Vertex[MAXVERTICES]; // all vertices in object
- int NumOfPolygons; // number of polygons in object
- PolygonTYPE Polygon[MAXPOLYGONS]; // all polygons in object
- } ObjectTYPE;
-
- ObjectTYPE Object; // one object
-
- int NumOfSortedPolygons; // number of sorted visible polygons
- int PolygonOrderList[MAXPOLYGONS]; // list of polygon indices for qsorting
-
- // structure of light source
- typedef struct
- {
- Fixedpoint x,y,z; // coodinates of light source
- Fixedpoint wx,wy,wz; // working (intermediate) coordinates
- int ax,ay,az; // rotation angles
- } LightSourceTYPE;
-
- LightSourceTYPE LightSource; // one light source
-
-
- int eboxtop1; // erase box top coordinate (current frame)
- int eboxbottom1; // erase box bottom coordinate (current frame)
- int eboxleft1; // erase box left coordinate (current frame)
- int eboxright1; // erase box right coordinate (current frame)
- int eboxtop2; // erase box top coordinate (one frame ago)
- int eboxbottom2; // erase box bottom coordinate (one frame ago)
- int eboxleft2; // erase box left coordinate (one frame ago)
- int eboxright2; // erase box right coordinate (one frame ago)
- int eboxtop3; // erase box top coordinate (two frames ago)
- int eboxbottom3; // erase box bottom coordinate (two frames ago)
- int eboxleft3; // erase box left coordinate (two frames ago)
- int eboxright3; // erase box right coordinate (two frames ago)
-
- // dot product, used for light source shading
- Fixedpoint DotProduct;
-
-
- //──────────────────────── function prototypes ───────────────────────────
-
- int main(void);
- void CreateLookupTables(void);
- void RotateObject(void);
- void LoadObject(void);
- void SortPolygons(void);
- int ComparePolygons(const void *a, const void *b);
- void DrawPolygons(void);
- void CalculateColor(void);
- void SetupLightSource(void);
- void RotateNormals(void);
- void RotateLightSource(void);
- void CalculateNormals(void);
- void GTriangle(float,float,float, float,float,float, float,float,float,int);
- void ScanEdge(float,float,float,float,float,float);
-
-
- //──────────────── code to create sin and cos lookup tables ──────────────
-
- void CreateLookupTables(void)
- {
- int i;
- for(i=0; i<MAXDEGREES; i++)
- {
- cosine[i]=Float2Fixed(cos((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
- sine[i] =Float2Fixed(sin((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
- }
- }
-
-
- //─────────────────────────────── rotate object ───────────────────────
-
-
- void RotateObject(void)
- {
- int i;
- Fixedpoint nx,ny,nz,cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
-
- VertexTYPE *vert; // pointer to a vertex structure
-
- // get the sine and cosine angles to save time from table lookup
- sinxangle=sine[Object.Ax];
- cosxangle=cosine[Object.Ax];
- sinyangle=sine[Object.Ay];
- cosyangle=cosine[Object.Ay];
- sinzangle=sine[Object.Az];
- coszangle=cosine[Object.Az];
-
- // initialize the erase-box info to the extreme values
- eboxtop1=240;
- eboxleft1=320;
- eboxright1=0;
- eboxbottom1=0;
-
- // loop through all vertices in object
- for(i=0;i<Object.NumOfVertices;i++)
- {
- vert=&Object.Vertex[i];
-
- // rotate around the x-axis
- vert->Vwz=FixedMul(vert->Voy,cosxangle) - FixedMul(vert->Voz,sinxangle);
- vert->Vwy=FixedMul(vert->Voy,sinxangle) + FixedMul(vert->Voz,cosxangle);
- vert->Vwx=vert->Vox;
-
- // rotate around the y-axis
- nx=FixedMul(vert->Vwx,cosyangle) - FixedMul(vert->Vwz,sinyangle);
- nz=FixedMul(vert->Vwx,sinyangle) + FixedMul(vert->Vwz,cosyangle);
- vert->Vwx=nx;
- vert->Vwz=nz;
-
- // rotate around the z-axis
- nx=FixedMul(vert->Vwx,coszangle) - FixedMul(vert->Vwy,sinzangle);
- ny=FixedMul(vert->Vwx,sinzangle) + FixedMul(vert->Vwy,coszangle);
- vert->Vwx=nx;
- vert->Vwy=ny;
-
- // project the 3-D coordinates to screen coordinates
- vert->Vsx=Fixed2Int(FixedMul(FixedDiv(vert->Vwx+Object.Ox,vert->Vwz+Object.Oz),EYE_DISTANCE)) + 160;
- vert->Vsy=Fixed2Int(FixedMul(FixedDiv(vert->Vwy+Object.Oy,vert->Vwz+Object.Oz),EYE_DISTANCE)) + 120;
- vert->Vsz=Fixed2Int(vert->Vwz+Object.Oz);
-
- // while we are at it, update the erase-box information
- if(vert->Vsx < eboxleft1) eboxleft1 = vert->Vsx;
- if(vert->Vsx > eboxright1) eboxright1 = vert->Vsx;
- if(vert->Vsy < eboxtop1) eboxtop1 = vert->Vsy;
- if(vert->Vsy > eboxbottom1) eboxbottom1 = vert->Vsy;
- }
-
- // clip the erase box
- if(eboxleft1<0) eboxleft1=0;
- if(eboxtop1<0) eboxtop1=0;
- if(eboxright1>319) eboxright1=319;
- if(eboxbottom1>239) eboxbottom1=239;
- }
-
-
- //─────────────────────── load object─────────────────────────────────────
-
-
- void LoadObject(void)
- {
- FILE *file;
- char filename[80];
- int i,j,temp,result;
-
- VertexTYPE *vert; // pointer to a vertex structure
-
- printf("LOAD OBJECT\n===========\n\n");
-
- // show the current directory's .V10 files
- result = system("dir *.v10 /w/p");
- if (result)
- {
- printf("\nSorry but couldn't list the V10 files of the current directory\n");
- }
-
- // get the filename from user
- printf("\n\nEnter filename (filename.V10) : ");
- gets(filename);
-
- // open the file to write to it
- if ((file = fopen(filename,"rb")) == NULL)
- {
- printf("\n\nCannot open input file.\n");
- }
- else
- {
- // okay file is ready to read data from it
-
- // read number of dots in file
- fread(&Object.NumOfVertices,sizeof(int),1,file);
-
- // read in all of the object's vertices
- for(i=0;i < Object.NumOfVertices; i++)
- {
- fread(&temp,sizeof(int),1,file);
- Object.Vertex[i].Vox=Int2Fixed(temp);
- fread(&temp,sizeof(int),1,file);
- Object.Vertex[i].Voy=Int2Fixed(temp);
- fread(&temp,sizeof(int),1,file);
- Object.Vertex[i].Voz=Int2Fixed(temp);
- }
-
- // read in the number of polygons
- fread(&Object.NumOfPolygons,sizeof(int),1,file);
- // read in the information for each polygon
- for(i=0; i < Object.NumOfPolygons; i++)
- {
- // read in the number of vertices in polygon
- fread(&Object.Polygon[i].NumOfVertices,sizeof(int),1,file);
- // read in the polygon's vertices (already in counter clockwise order)
- for(j=0; j< Object.Polygon[i].NumOfVertices; j++)
- {
- fread(&Object.Polygon[i].Vertex[j],sizeof(int),1,file);
- }
- // read the color of the polygon
- fread(&Object.Polygon[i].color,sizeof(int),1,file);
- }
-
- // we're finished, close the file
- fclose(file);
- printf("\n\nObject loaded.\n");
- }
- }
-
-
- //────────────────────────── make visible polygon list ─────────────────────
-
- void MakePolygonList(void)
- {
- int i,j,k;
-
- VertexTYPE *v0,*v1,*v2;
-
- j=0;
- for(i=0;i<Object.NumOfPolygons;i++)
- {
- v0=&Object.Vertex[Object.Polygon[i].Vertex[0]];
- v1=&Object.Vertex[Object.Polygon[i].Vertex[1]];
- v2=&Object.Vertex[Object.Polygon[i].Vertex[2]];
-
- // if expression results in a negative then polygon is visible
- if( ((v1->Vsx - v0->Vsx) * (v2->Vsy - v0->Vsy) - (v1->Vsy - v0->Vsy) * (v2->Vsx - v0->Vsx)) < 0 )
- {
- PolygonOrderList[j++]=i;
- }
- }
- NumOfSortedPolygons=j;
- }
-
- //──────────────────────────────────── sort polygons ───────────────────────
-
-
- void SortPolygons(void)
- {
- int i,j;
- int maxz,minz;
- int temp;
- PolygonTYPE *poly;
-
- // first find the distance of each polygon (from midpoint of max & min z's)
- for(i=0;i<Object.NumOfPolygons;i++)
- {
-
- poly=&Object.Polygon[i];
- minz=65535; // set to extreme values
- maxz=-65536; // set to extreme values
- for(j=0;j<poly->NumOfVertices;j++)
- {
- if(Object.Vertex[poly->Vertex[j]].Vsz < minz)
- {
- minz=Object.Vertex[poly->Vertex[j]].Vsz;
- }
- if(Object.Vertex[poly->Vertex[j]].Vsz > maxz)
- {
- maxz=Object.Vertex[poly->Vertex[j]].Vsz;
- }
- }
- // now calculate the distance
- poly->zcenter=(maxz+minz)>>1;
- }
-
- // qsort the polygons
- qsort((const void *)PolygonOrderList,NumOfSortedPolygons,sizeof(PolygonOrderList[0]),ComparePolygons);
- }
-
- //────────────────────────── compare zcenter (for qsort) ───────────────────
-
- int ComparePolygons(const void *a, const void *b)
- {
- if( Object.Polygon[*(int *)a].zcenter < Object.Polygon[*(int *)b].zcenter )
- {
- return -1;
- }
- else if( Object.Polygon[*(int *)a].zcenter > Object.Polygon[*(int *)b].zcenter )
- {
- return +1;
- }
- else
- {
- return 0;
- }
- }
-
- //──────────────────────────────────── draw polygons ───────────────────────
-
-
- void DrawPolygons(void)
- {
- int i,j;
-
- x_rect_fill(eboxleft3,eboxtop3,eboxright3+1,eboxbottom3+1,HiddenPageOffs,0);
-
- for(i=0;i<NumOfSortedPolygons;i++)
- {
- // loop through all vertices in polygon and draw triangular pieces
- for(j=0; j < Object.Polygon[PolygonOrderList[i]].NumOfVertices-2;j++)
- {
- GTriangle((float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[0]].Vsx,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[0]].Vsy,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[0]].shadedcolor,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[j+1]].Vsx,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[j+1]].Vsy,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[j+1]].shadedcolor,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[j+2]].Vsx,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[j+2]].Vsy,
- (float)Object.Vertex[Object.Polygon[PolygonOrderList[i]].Vertex[j+2]].shadedcolor,
- HiddenPageOffs);
- }
- }
-
- // update the older erase box information
- eboxtop3 = eboxtop2; eboxtop2 = eboxtop1;
- eboxleft3 = eboxleft2; eboxleft2 = eboxleft1;
- eboxright3 = eboxright2; eboxright2 = eboxright1;
- eboxbottom3 = eboxbottom2; eboxbottom2 = eboxbottom1;
-
- }
-
-
- //──────────────────────────── calculate normals ─────────────────────────
-
-
- void CalculateNormals(void)
- {
- double xlen,ylen,zlen,length;
-
- //This will calculate the normals of the vertices for gouraud shading
-
- for(int i=0;i < Object.NumOfVertices; i++)
- {
-
- // calculate perpendicular via the vertex and the vertex*2
- // ie. we are scaling the vertices and use them as the new vertices
- // for gouraud shading. This is not quite correct though, because
- // you wouldn't be accounting for polygons that face the object's
- // center.
- xlen = Fixed2Float(FixedMul(Object.Vertex[i].Vox,Int2Fixed(2)));
- ylen = Fixed2Float(FixedMul(Object.Vertex[i].Voy,Int2Fixed(2)));
- zlen = Fixed2Float(FixedMul(Object.Vertex[i].Voz,Int2Fixed(2)));
-
- // calculate the length of the normal
- length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
-
- // scale it to a unit normal
- Object.Vertex[i].Nox = Float2Fixed(xlen / length);
- Object.Vertex[i].Noy = Float2Fixed(ylen / length);
- Object.Vertex[i].Noz = Float2Fixed(zlen / length);
- }
- }
-
-
- //──────────────────────────── calculate color ───────────────────────────
-
- void CalculateColor(void)
- {
- int i;
- int color;
-
- for(i=0; i < Object.NumOfVertices; i++)
- {
- DotProduct=FixedMul(Object.Vertex[i].Nwx , LightSource.wx) +
- FixedMul(Object.Vertex[i].Nwy , LightSource.wy) +
- FixedMul(Object.Vertex[i].Nwz , LightSource.wz);
-
- Object.Vertex[i].shadedcolor = 56 + Fixed2Int(FixedMul(DotProduct,Int2Fixed(40)));
- }
- }
-
-
- //──────────────────────────── rotate normals ─────────────────────────────
-
-
- void RotateNormals(void)
- {
- int i;
- Fixedpoint nx,ny,nz,cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
- VertexTYPE *vert; // pointer to a vertex structure
-
- // get sine and cosine angles to save time from table lookup in inner loop
- sinxangle=sine[Object.Ax];
- cosxangle=cosine[Object.Ax];
- sinyangle=sine[Object.Ay];
- cosyangle=cosine[Object.Ay];
- sinzangle=sine[Object.Az];
- coszangle=cosine[Object.Az];
-
- for(i=0;i<Object.NumOfVertices;i++)
- {
- vert=&Object.Vertex[i];
-
- // rotate around the x-axis
- vert->Nwz=FixedMul(vert->Noy , cosxangle) - FixedMul(vert->Noz , sinxangle);
- vert->Nwy=FixedMul(vert->Noy , sinxangle) + FixedMul(vert->Noz , cosxangle);
- vert->Nwx=vert->Nox;
-
- // rotate around the y-axis
- nx=FixedMul(vert->Nwx , cosyangle) - FixedMul(vert->Nwz , sinyangle);
- nz=FixedMul(vert->Nwx , sinyangle) + FixedMul(vert->Nwz , cosyangle);
- vert->Nwx=nx;
- vert->Nwz=nz;
-
- // rotate around the z-axis
- nx=FixedMul(vert->Nwx , coszangle) - FixedMul(vert->Nwy , sinzangle);
- ny=FixedMul(vert->Nwx , sinzangle) + FixedMul(vert->Nwy , coszangle);
-
- // reverse the direction of the normals for lightsource shading
- vert->Nwx=-nx;
- vert->Nwy=-ny;
- vert->Nwz=-nz;
- }
- }
-
-
- //───────────────────── set up light source coordinates ──────────────────
-
-
- void SetupLightSource(void)
- {
- double xlen,ylen,zlen,length;
-
- // assign the delault light source position
- xlen=0;
- ylen=0;
- zlen=10;
-
- // calculate the length of the vector (light source to 0,0,0)
- length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
-
- // scale it to a unit vector
- LightSource.x = Float2Fixed(xlen/length);
- LightSource.y = Float2Fixed(ylen/length);
- LightSource.z = Float2Fixed(zlen/length);
- }
-
-
-
- //────────────────────── rotate light source ─────────────────────────────
-
-
- void RotateLightSource(void)
- {
- int i;
- Fixedpoint nx,ny,nz;
- Fixedpoint cosxangle,sinxangle,cosyangle,sinyangle,coszangle,sinzangle;
-
- // update the light source rotation angles
- LightSource.ax+=8; if(LightSource.ax>=MAXDEGREES) LightSource.ax=0;
- LightSource.ay+=8; if(LightSource.ay>=MAXDEGREES) LightSource.ay=0;
- LightSource.az+=8; if(LightSource.az>=MAXDEGREES) LightSource.az=0;
-
- // get sine and cosine angles to save time from table lookup in inner loop
- sinxangle=sine[LightSource.ax];
- cosxangle=cosine[LightSource.ax];
- sinyangle=sine[LightSource.ay];
- cosyangle=cosine[LightSource.ay];
- sinzangle=sine[LightSource.az];
- coszangle=cosine[LightSource.az];
-
- // rotate around the x-axis
- LightSource.wz=FixedMul(LightSource.y , cosxangle) - FixedMul(LightSource.z , sinxangle);
- LightSource.wy=FixedMul(LightSource.y , sinxangle) + FixedMul(LightSource.z , cosxangle);
- LightSource.wx=LightSource.x;
-
- // rotate around the y-axis
- nx=FixedMul(LightSource.wx, cosyangle) - FixedMul(LightSource.wz , sinyangle);
- nz=FixedMul(LightSource.wx, sinyangle) + FixedMul(LightSource.wz , cosyangle);
- LightSource.wx=nx;
- LightSource.wz=nz;
-
- // rotate around the z-axis
- nx=FixedMul(LightSource.wx , coszangle) - FixedMul(LightSource.wy , sinzangle);
- ny=FixedMul(LightSource.wx , sinzangle) + FixedMul(LightSource.wy , coszangle);
-
- // reverse the direction of the normals for lightsource shading
- LightSource.wx=-nx;
- LightSource.wy=-ny;
- LightSource.wz=-nz;
- }
-
-
-
- //─────────────────────────── MAIN PROGRAM ───────────────────────────────
-
-
- int main(void)
- {
- int y;
- char keypress;
-
- clrscr();
- printf("GOURAUD VECTORS\n by Tumblin / Bodies In Motion '95\n");
-
- LoadObject();
-
- printf("\n\nPress any key to begin, and again to end.\n\n");
- getch();
-
- CreateLookupTables();
-
- SetupLightSource();
- CalculateNormals();
-
- x_text_init();
-
- x_set_mode(X_MODE_320x240,320);
- x_set_doublebuffer(240);
- x_set_cliprect(0,0,79,239);
- x_put_pal_raw(palette,256,0); // setup VED 1.0 palette colors
-
- // initialize the position and angles of object
- Object.Ox=Int2Fixed(0);
- Object.Oy=Int2Fixed(0);
- Object.Oz=Int2Fixed(-1024);
- Object.Ax=0;
- Object.Ay=0;
- Object.Az=0;
-
- // run the demo until user hits key
- do
- {
- Object.Ax+=8; if(Object.Ax >=MAXDEGREES) Object.Ax=0;
- Object.Ay-=8; if(Object.Ay <0) Object.Ay=MAXDEGREES-1;
- Object.Az+=6; if(Object.Az >=MAXDEGREES) Object.Az=0;
- RotateObject();
- RotateNormals();
- RotateLightSource();
- CalculateColor();
- MakePolygonList();
- SortPolygons();
- DrawPolygons();
- x_page_flip(0,0);
- }while(!kbhit());
- getch();
-
- x_text_mode();
- printf("GOURAUD VECTORS\n");
- printf("coded by Tumblin / Bodies In Motion '95\n");
- printf("(aka Terry Sznober)\n");
- printf("You can email me at tumblin@mi.net\n");
- printf("Greetings to everyone in the demo scene!\n");
- printf("Special greets to all the cool people I met at NAID '95!\n");
- return(0);
- }
-
-
- //--------------------- Gouraud Shaded Triangle routine ------------------
-
-
- void GTriangle(float x1,float y1,float c1,
- float x2,float y2,float c2,
- float x3,float y3,float c3,
- int pageoffs)
- {
- float mx; // slope dy/dx
- float mc; // slope dc/dx
- float x; // x screen coordinate
- float c; // color of pixel to plot
- int count; // looping variable
- int y; // looping variable
- float cl; // color of left edge of horizontal scanline
- float cr; // color of right edge of horizontal scanline
- float el; // coordinate of left edge of horizontal scanline
- float er; // coordinate of right edge of horizontal scanline
-
-
- // initialize the edge buffers to extreme values
- for(count=0;count<240;count++)
- {
- edge_l[count]=319;
- edge_r[count]=0;
- }
-
- // scan the edges of the triangle
- ScanEdge(x1,y1,c1, x2,y2,c2);
- ScanEdge(x2,y2,c2, x3,y3,c3);
- ScanEdge(x3,y3,c3, x1,y1,c1);
-
- // gouraud fill the horizontal scanlines
- for(y=0;y<240;y++)
- {
- // if the scanline is valid (ie left coordinate < right coordinate)
- if(edge_l[y] <= edge_r[y])
- {
- cl=(float)color_l[y];
- cr=(float)color_r[y];
- el=(float)edge_l[y];
- er=(float)edge_r[y];
-
- // now calculate slope of color (dc/dx)
-
- if( (er-el) == 0)
- {
- // denominator will be zero so don't do the division so use dc
- mc = (cr-cl);
- }
- else
- {
- // denominator okay, so use dc/dx
- mc = (cr-cl)/(er-el);
- }
- c = cl; // start with color of left edge of scanline
- // loop through every pixel in horizontal scanline
- for(count=(int)edge_l[y]; count < (int)edge_r[y]; count++)
- {
- x_put_pix(count,y,pageoffs,(int)c);
- c+=mc; // increase the color by dc/dx
- }
- }
- }
- }
-
-
- void ScanEdge(float x1,float y1,float c1,float x2,float y2,float c2)
- {
- // scan-convert (x1,y1,c1)-(x2,y2,c2)
-
- float mx; // slope dx/dy
- float mc; // slope dc/dy
- float x; // x pixel coordinate
- float c; // pixel's color
- int count; // looping variable
- float temp; // used for swapping
-
- // make sure that edge goes from top to bottom
- if( (y2-y1) < 0 )
- {
- // swap y2 with y1
- temp=y1;
- y1=y2;
- y2=temp;
- // swap x2 with x1
- temp=x1;
- x1=x2;
- x2=temp;
- // swap c2 with c1
- temp=c1;
- c1=c2;
- c2=temp;
- }
-
- // initialize for stepping
- if( (y2-y1) != 0)
- {
- mx = (x2-x1)/(y2-y1); // dx/dy
- mc = (c2-c1)/(y2-y1); // dc/dy
- }
- else
- {
- mx = (x2-x1); // dx
- mc = (c2-c1); // dc
- }
- x = x1; // starting x coordinate
- c = c1; // starting c color
-
- // step through edge and record color values along the way
- for(count=y1; count < y2; count++)
- {
- if(x < (float)edge_l[count])
- {
- edge_l[count]=(int)x;
- color_l[count]=(int)c;
- }
- if(x > (float)edge_r[count])
- {
- edge_r[count]=(int)x;
- color_r[count]=(int)c;
- }
- x+=mx; // x = x + dx/dy
- c+=mc; // c = c + dc/dy
- }
- }
-